# bazel build @consensus_spec_tests//:test_data
# bazel build @consensus_spec_tests//:test_data --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly

def _get_redirected_url(repository_ctx, url, headers):
    if not repository_ctx.which("curl"):
        fail("curl is required to resolve redirect URLs")

    cmd = [
        "curl",
        "-sL",  # silent + follow redirects
        "-o", "NUL" if repository_ctx.os.name == "windows" else "/dev/null",
        "-w", "%{url_effective}",
        "-H", "Authorization: %s" % headers["Authorization"],
        "-H", "Accept: %s" % headers["Accept"],
        url,
    ]

    result = repository_ctx.execute(cmd, quiet = True)
    if result.return_code != 0:
        fail("curl failed to resolve redirected URL: %s" % result.stderr)
    return result.stdout.strip()

def _impl(repository_ctx):
    version = repository_ctx.getenv("CONSENSUS_SPEC_TESTS_VERSION") or repository_ctx.attr.version
    token = repository_ctx.getenv("GITHUB_TOKEN") or ""

    if version == "nightly":
        print("Downloading nightly tests")
        if not token:
            fail("Error GITHUB_TOKEN is not set")

        headers = {
            "Authorization": "token %s" % token,
            "Accept": "application/vnd.github+json",
        }

        repository_ctx.download(
            "https://api.github.com/repos/%s/actions/workflows/%s/runs?branch=%s&status=success&per_page=1"
                % (repository_ctx.attr.repo, repository_ctx.attr.workflow, repository_ctx.attr.branch),
            headers = headers,
            output = "runs.json"
        )

        run_id = json.decode(repository_ctx.read("runs.json"))["workflow_runs"][0]["id"]
        repository_ctx.delete("runs.json")

        repository_ctx.download(
            "https://api.github.com/repos/%s/actions/runs/%s/artifacts"
                % (repository_ctx.attr.repo, run_id),
            headers = headers,
            output = "artifacts.json"
        )

        artifacts = json.decode(repository_ctx.read("artifacts.json"))["artifacts"]
        repository_ctx.delete("artifacts.json")

        for artifact in artifacts:
            name = artifact["name"]
            if name == "consensustestgen.log":
                continue
            url = artifact["archive_download_url"]
            # Ugh this is the worst, bazel doesn't follow redirects...
            resolved_url = _get_redirected_url(repository_ctx, url, headers)
            repository_ctx.download_and_extract(resolved_url)
            tar_gz_file = "%s.tar.gz" % name.split(" ")[0].lower()
            repository_ctx.extract(tar_gz_file)
            repository_ctx.delete(tar_gz_file)
    else:
        for flavor in repository_ctx.attr.flavors:
            integrity = repository_ctx.attr.flavors[flavor]
            url = "%s/%s.tar.gz" % (repository_ctx.attr.release_url_template % version, flavor)
            repository_ctx.download_and_extract(url, integrity = integrity)

    repository_ctx.file("BUILD.bazel", """
filegroup(
    name = "general_tests",
    srcs = glob(["tests/general/**/*.yaml", "tests/general/**/*.ssz_snappy"]),
    visibility = ["//visibility:public"],
)

filegroup(
    name = "mainnet_tests",
    srcs = glob(["tests/mainnet/**/*.yaml", "tests/mainnet/**/*.ssz_snappy"]),
    visibility = ["//visibility:public"],
)

filegroup(
    name = "minimal_tests",
    srcs = glob(["tests/minimal/**/*.yaml", "tests/minimal/**/*.ssz_snappy"]),
    visibility = ["//visibility:public"],
)

filegroup(
    name = "test_data",
    srcs = [
        ":general_tests",
        ":mainnet_tests",
        ":minimal_tests",
    ],
    visibility = ["//visibility:public"],
)
""")

consensus_spec_tests = repository_rule(
    implementation = _impl,
    environ = ["CONSENSUS_SPEC_TESTS_VERSION", "GITHUB_TOKEN"],
    attrs = {
        "version": attr.string(mandatory = True),
        "flavors": attr.string_dict(mandatory = True),
        "repo": attr.string(default = "ethereum/consensus-specs"),
        "workflow": attr.string(default = "generate_vectors.yml"),
        "branch": attr.string(default = "dev"),
        "release_url_template": attr.string(default = "https://github.com/ethereum/consensus-specs/releases/download/%s"),
    },
)
